package org.wizehack.mri.testSet;

import java.util.ArrayList;
import java.util.List;

import org.wizehack.mri.CoverageDataParser.SourceFile;
import org.wizehack.mri.test.BasicTestSuite;
import org.wizehack.mri.test.TestCase;
import org.wizehack.mri.test.TestSuite;

public class SimilaritybasedSelectionStrategy extends TestCaseReductionExt {
	private double threshold;
	private static int FAILED_TEST_CASE = 0;
			
	public SimilaritybasedSelectionStrategy(double threshold) {
		super();
		this.threshold = threshold;
	}

	@Override
	public List<TestSuite> createTestSuiteList(TestSuite testSuite) {
		List<TestSuite> testSuiteList = new ArrayList<TestSuite>();;

		super.setTestSuite(testSuite);
		TestSuite tSuite = super.select();
		
		List<String> failedCoverageFileList = super.getFailedCoverageFileList();
		
//		for(int i=0; i<tSuite.size(); i++){
//			System.out.println("tc: " + tSuite.get(i).getCoverageLocation()); //check ok
//		}
		
//		for(int i=0; i<failedCoverageFileList.size(); i++){
//			System.out.println("failed TC: " + failedCoverageFileList.get(i)); //check ok
//		}
		
		if(failedCoverageFileList != null){
			
			for(int i=0; i<tSuite.size(); i++){
				TestCase testCase = tSuite.get(i);
				if(failedCoverageFileList.contains(testCase.getCoverageLocation())){		
//					System.out.println("testCase.getCoverageLocation(): " + testCase.getCoverageLocation());
					TestSuite newTestSuite = new BasicTestSuite();
					newTestSuite.add(testCase);
					testSuiteList.add(newTestSuite);
					testSuite.remove(testCase);
					i--;
				}
			}

			for(int i=0; i<testSuiteList.size(); i++){
				TestSuite newSuite = testSuiteList.get(i);
				
				for(int j=0; j<testSuite.size(); j++){
					
					double similarity = calculateSimilarity(testSuiteList.get(i).get(FAILED_TEST_CASE), testSuite.get(j));
										
					if(similarity >= this.threshold){
						newSuite.add(testSuite.get(j));
					}
				}
			}
		}
		
		return testSuiteList;
	}

	@Override
	public List<TestSuite> select(List<TestSuite> testSuiteList) {
		List<TestSuite> tSuiteList = new ArrayList<TestSuite>();
		List<TestSuite> result = new ArrayList<TestSuite>();
		for(int i=0; i<testSuiteList.size(); i++){
			tSuiteList = this.createTestSuiteList(testSuiteList.get(i));
			for(int j=0; j<tSuiteList.size(); j++){
				TestSuite testSuite = tSuiteList.get(j);
				result.add(testSuite);
			}
		}
		
		return result;
	}
	
	public double calculateSimilarity(TestCase failedTestCase, TestCase passedTestCase){
		double similarity = 0;
		int sameLine = 0;
		int fLength = 0;

		List<SourceFile> sFailedFileList = failedTestCase.getCoverage();
		List<SourceFile> sPassedFileList = passedTestCase.getCoverage();

		
		for(int i=0; i<sFailedFileList.size(); i++){
			SourceFile sFailedFile = sFailedFileList.get(i);
			
			fLength = fLength + sFailedFile.size();
		}
		
		for(int i=0; i<sFailedFileList.size(); i++){
			SourceFile sFailedFile = sFailedFileList.get(i);
			String fFileName = sFailedFile.getName();

			for(int j=0; j<sPassedFileList.size(); j++){
				SourceFile sPassedFile = sPassedFileList.get(j);
				String pFileName = sPassedFile.getName();
				
				if(fFileName.equals(pFileName)){
					for(int k=0; k<sFailedFile.size() && k<sPassedFile.size(); k++){
						
						if( sFailedFile.get(k).getLineNumber() == sPassedFile.get(k).getLineNumber() ){
							sameLine++;
						}
					}
					break;
				}
			}
		}
		
		similarity = (double) sameLine / (double) fLength ;
//		System.out.println(similarity);
		
		return similarity;
	}

	



}
